/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fs.genomemap;

import genomemap.data.ChData;
import genomemap.data.Clone;
import genomemap.data.Gene;
import genomemap.data.Probe;
import genomemap.worker.ProgCurve;

import gui.genomemap.outputModel.OutputModel;

import javautil.collections.ArrayUtil;
import javautil.collections.SetUtil;
import javautil.io.IOUtil;
import javautil.lang.ReflectionUtil;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Settings related to file system
 * @author Susanta Tewari
 * @version 1.0
 * @updated 20-Nov-2007 7:37:56 PM
 */
public class FileSettings implements Serializable {

    /** Field description */
    private static FileSettings loadedFileSettings = null;

    /** Field description */
    private static final long serialVersionUID = 42L;

    /** Field description */
    private static final String ownPath = "resources/FileSettings.obj";

    /** Field description */
    public static final String dataCollectionDir = "resources/dataCollection/";

    /** Field description */
    private static final String outputModelsDir = "resources/outputModels/";

    /**
     * input file names and patterns.pattern fle names (end with PTRN) will have
     * 7 files with names by appending <CODE>i.txt</CODE> where <CODE>i</CODE> represents
     * the chromosome id: starts from 1 to 7. File names are relative to the<CODE>dataCollectionDir</CODE>
     * This is a pattern file for clone names.<B>Integrity check is necessary for this file</B>.
     * The order of the names corresponds to the rows (clones) in the hybridization
     * file for the correspinding chromosome.
     */
    public static final String FILE_CLONE_NAME_PTRN = "clone_names_";

    /**
     * This has sequence information( base pair <I>start</I> and <I>end</I> values)
     * for all the clones. No integrity check is necessary for this file. No particular
     * collection of clones needed to be present. Just bigger the colection better
     * it is.
     */
    public static final String FILE_CLONE_START_END_BANK = "clone_start_end_bank.txt";

    /**
     * This is a pattern file. <B>Integrity check is necessary for this file</B>.The gene names
     * with their rowIds (integer appearing next to the name) correspond to a row in the rflp file.
     * Note that a single rowId corresponds to a particular locus in the rflp file and may have multiple
     * gene names.
     */
    public static final String FILE_GENE_ROW_ID_PTRN = "geneRowId_";

    /**
     * <B>Integrity check is not necessary for this file</B>. In a line the first string refers to
     * a gene name followed by clone names (some of which may be probes). The tagging information
     * could be obrained from a variety of sources. Below is a description.
     * (1) Some are linked by using the cosmid to complement a mutation in the gene.
     * (2) Some are done by hybridizing a gene sequence to the cosmid library.
     * (3) Some were identified from sequences associated with the cosmid.
     */
    private static final String FILE_GENE_CLONE_COMPLE_DATA = "gene_clone_complementation_data.txt";

    /**
     * This is a pattern file. <B>Integrity check is not necessary on this file</B>. It contains gene names followed by their ncu names. <CODE>ncu</CODE>
     * nomenclature is used to identify a single gene which is generally used to get sequence
     * information.
     */
    public static final String FILE_GENE_NCU_PTRN = "gene_ncu_";

    /**
     * This is a pattern file. <B>Integrity check is paramount on this file</B>. This contains the
     * hybridization data of clones (rows) on the probes(columns). Separate integrity checked files
     * for the names of clones and probes are also made part of the input data collection.
     * <B>The following integrity checks are performed on the file:</B>
     */
    public static final String FILE_HYBRID_PTRN = "hybrid_";

    /**
     * This has sequence information( base pair <I>start</I> and <I>end</I> values)
     * for all the <CODE>ncus</CODE>. <B>No integrity check is necessary for this file</B>. No particular
     * collection of ncus needed to be present. Just bigger the colection the better
     * it is.
     */
    public static final String FILE_NCU_START_END_BANK = "ncu_start_end_bank.txt";

    /**
     * This is a pattern file. <B>Integrity check is necessary for this file</B>. It contains the probe
     * names in the order they appeared on the columns of the hybridization file. The total number must also
     * match.
     */
    public static final String FILE_PROBE_NAMES_PTRN = "probe_names_";

    /**
     * This is a pattern file. <B>Integrity check is paramount on this file</B>. This contains the
     * <CODE>rflp</CODE> data of genotypes for a collection of progeney (columns). A separate integrity
     * checked file <I>geneRowId_{i}.txt</I> refer to the gene rows (represented by their ids and correspond to a locus)
     * with its gene names. Mutiple genes may be found on a single locus (of course due to the low resolution
     * of the genetic map) and thus correspond to the same geneRowid.
     * <B>The following integrity checks are performed on the file:</B>
     */
    public static final String FILE_RFLP_PTRN = "rflp_";

    /**
     * This is a pattern file. This contains the probe counts with their expected
     * contig counts. <B>Integrity check is necessary for this file</B>
     */
    private static final String FILE_EXP_PROG_CURVE_PTRN = "exp_prog_curve_";

    /**
     * key: the name of the View class(e.g., ComGLHoodView)
     * value: the .obj file path required to marshall <CODE>Set<OutputModel></CODE> for the
     * corresponding view.
     * This will also contain object files for colections of Gene,Probe and Clone with the
     * respective class names mapped with chromosome id.
     * Map<Integer,Set<Gene>> geneSetMap,Map<Integer,Set<Probe>> probeSetMap
     * and Map<Integer,Set<Clone>> cloneSetMap
     */
    private final Map<String, String> objFiles = new Hashtable<>();

    /**
     * collection of ChData.ChData contains some parameters on the physical data
     * and references to files such as RFLP and Hybridization data.
     */
    private final Map<Integer, ChData> chDataMap = new Hashtable<>();

    /**
     * Constructs ...
     */
    public FileSettings() {}

    public static void main(String[] args) {

        for (int i = 0; i < 7; i++) {


            // String hybridPath = "resources/dataCollection/hybrid_"+(i+1)+".txt";
            String probe_final_order_names_filepath =
                "resources/dataCollection/final_probe_order_names/final_probe_order_names_"
                + (i + 1) + ".txt";
            String origin_probe_names_filepath = "resources/dataCollection/probe_names_" + (i + 1)
                                                 + ".txt";
            int[] probeOrder = getOrderFromProbeNames(origin_probe_names_filepath,
                                   probe_final_order_names_filepath);

            System.out.println(IOUtil.toString(ArrayUtil.getIntegerArray(probeOrder), ","));
        }
    }

    /**
     * all the probe names in orgin_probe_names that are present in new_probe_names will have their
     * order altered according to new_probe_names while the rest (the probes not present in new_probe_names) will also
     * have their order intact.
     * @param orgin_probe_names_filepath
     * @param new_probe_names_filepath
     * @return
     */
    private static int[] getOrderFromProbeNames(String orgin_probe_names_filepath,
            String new_probe_names_filepath) {

        String[] new_probe_names   = null;
        String[] orgin_probe_names = null;

        try {

            orgin_probe_names = IOUtil.getTokens(
                IOUtil.readFileContentToString(new File(orgin_probe_names_filepath)), null);
            new_probe_names = IOUtil.getTokens(
                IOUtil.readFileContentToString(new File(new_probe_names_filepath)), null);

        } catch (Exception exception) {
            exception.printStackTrace();
        }

        new_probe_names = (String[]) SetUtil.getEmbeddedSeq(orgin_probe_names,
                new_probe_names).toArray(new String[0]);


        // print(orgin_probe_names);
        // print(new_probe_names);
        int[] result  = new int[orgin_probe_names.length];
        boolean found = false;

        for (int i = 0; i < orgin_probe_names.length; i++) {

            found = false;

            for (int j = 0; j < orgin_probe_names.length; j++) {

                if (new_probe_names[i].equals(orgin_probe_names[j])) {

                    result[i] = (j + 1);
                    found     = true;

                    break;
                }
            }

            if (!found) {

                System.out.println(" New Probe : " + new_probe_names[i]
                                   + " wasn`t found in the original file");


                // System.exit(0);
            }
        }

        return result;
    }

    public ChData getChData(int ch_id) {
        return chDataMap.get(new Integer(ch_id));
    }

    public Map<Integer, Integer> getExpProgCurveMap(int ch_id) {
        return getExpProgCurveMap().get(new Integer(ch_id));
    }

    public Map<Integer, ChData> getChDataMap() {
        return chDataMap;
    }

    public Set<Gene> getGeneSet(int ch_id) {
        return getGeneSetMap().get(new Integer(ch_id));
    }

    public Set<Probe> getProbeSet(int ch_id) {
        return getProbeSetMap().get(new Integer(ch_id));
    }

    public Set<Clone> getCloneSet(int ch_id) {
        return getCloneSetMap().get(new Integer(ch_id));
    }

    Map<Integer, Map<Integer, Integer>> getExpProgCurveMap() {

        try {

            return (Map<Integer,
                        Map<Integer, Integer>>) IOUtil.unMarshall(
                            new File(getObjectFilePath(ProgCurve.class)));

        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        return null;
    }

    Map<Integer, Set<Gene>> getGeneSetMap() {

        try {

            return (Map<Integer,
                        Set<Gene>>) IOUtil.unMarshall(new File(getObjectFilePath(Gene.class)));

        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        return null;
    }

    Map<Integer, Set<Probe>> getProbeSetMap() {

        try {

            return (Map<Integer,
                        Set<Probe>>) IOUtil.unMarshall(new File(getObjectFilePath(Probe.class)));

        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        return null;
    }

    Map<Integer, Set<Clone>> getCloneSetMap() {

        try {

            return (Map<Integer,
                        Set<Clone>>) IOUtil.unMarshall(new File(getObjectFilePath(Clone.class)));

        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        return null;
    }

    /**
     * checks if all the necessary input files are present. Returns and string of file name
     * that are not present. If all are ok, returns <CODE>null</CODE>.
     */
    public static String checkInputCollection() {

        String errStr                   = "";
        Collection<File> fileCollection = getInputFileCollection();

        for (File file : fileCollection) {

            if (!file.exists()) {
                errStr += file.getAbsolutePath() + "\n";
            }
        }

        if (errStr.length() > 0) {
            return "The following files don`t exist in the system: \n" + errStr;
        }

        return null;
    }

    public static String checkSeqInfoUpdateFiles() {

        String errStr                   = "";
        Collection<File> fileCollection = new HashSet<>();

        fileCollection.addAll(getFilesForPattern(FILE_GENE_NCU_PTRN));
        fileCollection.add(new File(dataCollectionDir + FILE_CLONE_START_END_BANK));

        for (File file : fileCollection) {

            if (!file.exists()) {
                errStr += file.getAbsolutePath() + "\n";
            }
        }

        if (errStr.length() > 0) {
            return "The following files don`t exist in the system: \n" + errStr;
        }

        return null;
    }

    /**
     * gives the collection of input files. Note files may not actually exist.
     *
     * @return description
     */
    private static Collection<File> getInputFileCollection() {

        Collection<File> fileCollection = new HashSet<>();


        // pattern files:
        // FILE_CLONE_NAME_PTRN, FILE_GENE_ROW_ID_PTRN, FILE_GENE_NCU_PTRN
        // FILE_HYBRID_PTRN, FILE_PROBE_NAMES_PTRN, FILE_RFLP_PTRN
        fileCollection.addAll(getFilesForPattern(FILE_CLONE_NAME_PTRN));
        fileCollection.addAll(getFilesForPattern(FILE_GENE_ROW_ID_PTRN));
        fileCollection.addAll(getFilesForPattern(FILE_GENE_NCU_PTRN));
        fileCollection.addAll(getFilesForPattern(FILE_HYBRID_PTRN));
        fileCollection.addAll(getFilesForPattern(FILE_PROBE_NAMES_PTRN));
        fileCollection.addAll(getFilesForPattern(FILE_RFLP_PTRN));
        fileCollection.addAll(getFilesForPattern(FILE_EXP_PROG_CURVE_PTRN));


        // NON-PATTERN files
        // FILE_CLONE_START_END_BANK, FILE_GENE_CLONE_COMPLE_DATA
        // FILE_NCU_START_END_BANK
        fileCollection.add(new File(dataCollectionDir + FILE_CLONE_START_END_BANK));
        fileCollection.add(new File(dataCollectionDir + FILE_GENE_CLONE_COMPLE_DATA));
        fileCollection.add(new File(dataCollectionDir + FILE_NCU_START_END_BANK));

        return fileCollection;
    }

    /**
     * Method description
     *
     * @param pattern description
     *
     * @return description
     */
    private static Collection<File> getFilesForPattern(String pattern) {

        Collection<File> fileCollection = new HashSet<>();

        for (int i = 1; i <= 7; i++) {

            fileCollection.add(new File(dataCollectionDir + pattern + i + ".txt"));
        }

        return fileCollection;
    }

    public static FileSettings load() {

        if (loadedFileSettings == null) {

            try {
                loadedFileSettings = (FileSettings) IOUtil.unMarshall(new File(ownPath));
            } catch (FileNotFoundException ex) {
                Logger.getLogger(FileSettings.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException | ClassNotFoundException ex) {
                Logger.getLogger(FileSettings.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        return loadedFileSettings;
    }


    // @todo could be generalized class independent code
    public boolean commit() {

        boolean result = true;

        try {
            IOUtil.marshall(new File(ownPath), this);
        } catch (Exception ex) {

            ex.printStackTrace();

            result = false;

        } finally {
            return result;
        }
    }

    /**
     * this will be invoked once during installation
     */
    public void addOutputModelCollectionPath(Class cls) {

        objFiles.put(cls.getName(),
                     outputModelsDir + ReflectionUtil.getClassName(cls) + "Collection.obj");
    }

    String getObjectFilePath(Class cls) {
        return objFiles.get(cls.getName());
    }

    public Collection<OutputModel> loadOutputModelCollection(Class cls) {

        Collection<OutputModel> outputModels = null;
        String objFilePath                   = getObjectFilePath(cls);

        if (objFilePath == null) {
            return null;
        }

        try {
            outputModels = (Collection<OutputModel>) IOUtil.unMarshall(new File(objFilePath));
        } catch (IOException | ClassNotFoundException ex) {
            ex.printStackTrace();
        } finally {
            return outputModels;
        }
    }

    public boolean saveOutputModels(Collection<? extends OutputModel> outputModels) {

        boolean result = true;

        if (outputModels.isEmpty()) {
            return false;
        }

        OutputModel outputModel = outputModels.iterator().next();
        String objFilePath      = getObjectFilePath(outputModel.getClass());

        if (objFilePath == null) {
            return false;
        }

        try {
            IOUtil.marshall(new File(objFilePath), outputModels);
        } catch (Exception ex) {

            ex.printStackTrace();

            result = false;

        } finally {
            return result;
        }
    }

    public void createChDataMap() {


        // chromosome -I
        ChData data1 = new ChData();

        data1.setChId(1);
        data1.setChLength(10300);
        data1.setCloneLength(34);
        data1.setProbeCount(237);
        data1.setCloneCount(4176);
        data1.setProbFalsePos(0.002);
        data1.setProbFalseNeg(0.002);
        data1.setGeneCount(53);
        data1.setRflpDataFilePath(dataCollectionDir + FILE_RFLP_PTRN + data1.getChId() + ".txt");
        data1.setHybridDataFilePath(dataCollectionDir + FILE_HYBRID_PTRN + data1.getChId()
                                    + ".txt");
        data1.setHybridTable("hybrid_" + data1.getChId());


        // chromosome -II
        ChData data2 = new ChData();

        data2.setChId(2);
        data2.setChLength(4600);
        data2.setCloneLength(34);
        data2.setProbeCount(210);
        data2.setCloneCount(2046);
        data2.setProbFalsePos(0.002);
        data2.setProbFalseNeg(0.002);
        data2.setGeneCount(39);
        data2.setRflpDataFilePath(dataCollectionDir + FILE_RFLP_PTRN + data2.getChId() + ".txt");
        data2.setHybridDataFilePath(dataCollectionDir + FILE_HYBRID_PTRN + data2.getChId()
                                    + ".txt");
        data2.setHybridTable("hybrid_" + data2.getChId());


        // chromosome -III
        ChData data3 = new ChData();

        data3.setChId(3);
        data3.setChLength(5100);
        data3.setCloneLength(34);
        data3.setProbeCount(181);
        data3.setCloneCount(1937);
        data3.setProbFalsePos(0.002);
        data3.setProbFalseNeg(0.002);
        data3.setGeneCount(31);
        data3.setRflpDataFilePath(dataCollectionDir + FILE_RFLP_PTRN + data3.getChId() + ".txt");
        data3.setHybridDataFilePath(dataCollectionDir + FILE_HYBRID_PTRN + data3.getChId()
                                    + ".txt");
        data3.setHybridTable("hybrid_" + data3.getChId());


        // chromosome -IV
        ChData data4 = new ChData();

        data4.setChId(4);
        data4.setChLength(5700);
        data4.setCloneLength(34);
        data4.setProbeCount(226);
        data4.setCloneCount(2497);
        data4.setProbFalsePos(0.002);
        data4.setProbFalseNeg(0.002);
        data4.setGeneCount(39);
        data4.setRflpDataFilePath(dataCollectionDir + FILE_RFLP_PTRN + data4.getChId() + ".txt");
        data4.setHybridDataFilePath(dataCollectionDir + FILE_HYBRID_PTRN + data4.getChId()
                                    + ".txt");
        data4.setHybridTable("hybrid_" + data4.getChId());


        // chromosome -V
        ChData data5 = new ChData();

        data5.setChId(5);
        data5.setChLength(9200);
        data5.setCloneLength(34);
        data5.setProbeCount(285);
        data5.setCloneCount(4351);
        data5.setProbFalsePos(0.002);
        data5.setProbFalseNeg(0.002);
        data5.setGeneCount(53);
        data5.setRflpDataFilePath(dataCollectionDir + FILE_RFLP_PTRN + data5.getChId() + ".txt");
        data5.setHybridDataFilePath(dataCollectionDir + FILE_HYBRID_PTRN + data5.getChId()
                                    + ".txt");
        data5.setHybridTable("hybrid_" + data5.getChId());


        // chromosome -VI
        ChData data6 = new ChData();

        data6.setChId(6);
        data6.setChLength(4000);
        data6.setCloneLength(34);
        data6.setProbeCount(176);
        data6.setCloneCount(1990);
        data6.setProbFalsePos(0.002);
        data6.setProbFalseNeg(0.002);
        data6.setGeneCount(31);
        data6.setRflpDataFilePath(dataCollectionDir + FILE_RFLP_PTRN + data6.getChId() + ".txt");
        data6.setHybridDataFilePath(dataCollectionDir + FILE_HYBRID_PTRN + data6.getChId()
                                    + ".txt");
        data6.setHybridTable("hybrid_" + data6.getChId());


        // chromosome -VII
        ChData data7 = new ChData();

        data7.setChId(7);
        data7.setChLength(4000);
        data7.setCloneLength(34);
        data7.setProbeCount(165);
        data7.setCloneCount(1746);
        data7.setProbFalsePos(0.002);
        data7.setProbFalseNeg(0.002);
        data7.setGeneCount(31);
        data7.setRflpDataFilePath(dataCollectionDir + FILE_RFLP_PTRN + data7.getChId() + ".txt");
        data7.setHybridDataFilePath(dataCollectionDir + FILE_HYBRID_PTRN + data7.getChId()
                                    + ".txt");
        data7.setHybridTable("hybrid_" + data7.getChId());
        chDataMap.put(new Integer(1), data1);
        chDataMap.put(new Integer(2), data2);
        chDataMap.put(new Integer(3), data3);
        chDataMap.put(new Integer(4), data4);
        chDataMap.put(new Integer(5), data5);
        chDataMap.put(new Integer(6), data6);
        chDataMap.put(new Integer(7), data7);
    }

    public void createExpProgCurveMap() {

        try {

            objFiles.put(ProgCurve.class.getName(), dataCollectionDir + "ProgCurveMap.obj");

            Map<Integer, Map<Integer, Integer>> expProgCurveMap = new Hashtable<>();

            for (int ch_id_index = 0; ch_id_index < 7; ch_id_index++) {


                // get expected prog curve: probe counts with their contig counts
                int[][] exp_progCurve_info               = null;
                Map<Integer, Integer> singleProgCurveMap = new Hashtable<>();
                String exp_progCurve_filePath = FileSettings.dataCollectionDir
                                                + FileSettings.FILE_EXP_PROG_CURVE_PTRN
                                                + (ch_id_index + 1) + ".txt";

                exp_progCurve_info = ArrayUtil.get2DIntArray(new File(exp_progCurve_filePath),
                        false, ",");

                for (int index = 0; index < exp_progCurve_info.length; index++) {

                    singleProgCurveMap.put(new Integer(exp_progCurve_info[index][0]),
                                           new Integer(exp_progCurve_info[index][1]));
                }

                expProgCurveMap.put(new Integer(ch_id_index + 1), singleProgCurveMap);
            }

            IOUtil.marshall(new File(getObjectFilePath(ProgCurve.class)), expProgCurveMap);

        } catch (FileNotFoundException ex) {
            Logger.getLogger(FileSettings.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(FileSettings.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void createGeneSetMap() {

        objFiles.put(Gene.class.getName(), dataCollectionDir + "GeneSet.obj");

        Map<Integer, Set<Gene>> geneSetMap = new Hashtable<>();

        try {


            // create a Map of Genes (Key) with NCUs(Value)
            Map<String, String> gene_ncu_Map   = new Hashtable<>();
            Map<String, Integer> ncu_index_Map = new Hashtable<>();
            Set<Gene> masterGeneSet            = new HashSet<>();

            for (int ch_id_index = 0; ch_id_index < 7; ch_id_index++) {


                // get geneRowId file path
                String geneRowId_filePath = FileSettings.dataCollectionDir
                                            + FileSettings.FILE_GENE_ROW_ID_PTRN
                                            + (ch_id_index + 1) + ".txt";
                String[][] geneRowId_info =
                    ArrayUtil.ReadRaggedStr2DArray(new File(geneRowId_filePath), false, ",");
                Set<Gene> geneSet = new HashSet<>();

                for (int geneIndex = 0; geneIndex < geneRowId_info.length; geneIndex++) {

                    Gene gene = new Gene();

                    gene.setLabel(geneRowId_info[geneIndex][0]);
                    gene.setOrder(geneIndex + 1);
                    gene.setChId(ch_id_index + 1);
                    geneSet.add(gene);
                }

                masterGeneSet.addAll(geneSet);
                geneSetMap.put(new Integer(ch_id_index + 1), geneSet);

                String gene_ncu_filePath = FileSettings.dataCollectionDir
                                           + FileSettings.FILE_GENE_NCU_PTRN + (ch_id_index + 1)
                                           + ".txt";
                String[][] gene_ncu_info =
                    ArrayUtil.ReadRaggedStr2DArray(new File(gene_ncu_filePath), false, " ");

                for (int ncuIndex = 0; ncuIndex < gene_ncu_info.length; ncuIndex++) {

                    gene_ncu_Map.put(gene_ncu_info[ncuIndex][0], gene_ncu_info[ncuIndex][1]);
                }
            }


            // read the ncu_start_end bank and create a map for ncu(key) with index(value)
            String ncu_start_end_bank_filePath = FileSettings.dataCollectionDir
                                                 + FileSettings.FILE_NCU_START_END_BANK;
            String[][] ncu_start_end_info =
                ArrayUtil.ReadRaggedStr2DArray(new File(ncu_start_end_bank_filePath), false, " ");

            for (int ncuIndex = 0; ncuIndex < ncu_start_end_info.length; ncuIndex++) {

                ncu_index_Map.put(ncu_start_end_info[ncuIndex][0], new Integer(ncuIndex));
            }


            // add the sequence info to the genes
            Iterator<Gene> itrGene = masterGeneSet.iterator();

            while (itrGene.hasNext()) {

                Gene gene  = itrGene.next();
                String ncu = gene_ncu_Map.get(gene.getLabel());

                if (ncu != null) {

                    Integer indexObj = ncu_index_Map.get(ncu);

                    if (indexObj != null) {

                        int index = indexObj.intValue();

                        gene.setStartPos(Integer.parseInt(ncu_start_end_info[index][1]));
                        gene.setEndPos(Integer.parseInt(ncu_start_end_info[index][1]));
                    }
                }
            }

            IOUtil.marshall(new File(getObjectFilePath(Gene.class)), geneSetMap);
        } catch (IOException | NumberFormatException e) {
            e.printStackTrace();
        }
    }

    public void createProbeSetMap() {

        objFiles.put(Probe.class.getName(), dataCollectionDir + "ProbeSet.obj");

        Map<Integer, Set<Probe>> probeSetMap = new Hashtable<>();

        try {

            Map<String, Integer> clone_index_Map = new Hashtable<>();
            Set<Probe> masterProbeSet            = new HashSet<>();

            for (int ch_id_index = 0; ch_id_index < 7; ch_id_index++) {


                // get probe names
                String probe_names_filePath = FileSettings.dataCollectionDir
                                              + FileSettings.FILE_PROBE_NAMES_PTRN
                                              + (ch_id_index + 1) + ".txt";
                String[] probe_names = IOUtil.getTokens(
                                           IOUtil.readFileContentToString(
                                               new File(probe_names_filePath)), null);
                Set<Probe> probeSet = new HashSet<>();

                for (int probeIndex = 0; probeIndex < probe_names.length; probeIndex++) {

                    Probe probe = new Probe();

                    probe.setLabel(probe_names[probeIndex]);
                    probe.setOrder(probeIndex + 1);
                    probe.setChId(ch_id_index + 1);
                    probeSet.add(probe);
                }

                masterProbeSet.addAll(probeSet);
                probeSetMap.put(new Integer(ch_id_index + 1), probeSet);
            }


            // add linkage groups for each probe by their labels
            Iterator<Probe> itr1 = masterProbeSet.iterator();

            while (itr1.hasNext()) {

                Probe probe1         = itr1.next();
                Iterator<Probe> itr2 = masterProbeSet.iterator();

                while (itr2.hasNext()) {

                    Probe probe2 = itr2.next();

                    if (probe1.getLabel().equals(probe2.getLabel())) {
                        probe1.addLinkageGroup(probe2.getChId());
                    }
                }

                int linkGrpCount = probe1.getLinkageGroupSet().size();

                if (linkGrpCount == 7) {


                    // System.out.println("Probe: " + probe1.getLabel() + " is an A probe.");
                }
            }


            // read the clone_start_end bank and create a map for clone(key) with index(value)
            String clone_start_end_bank_filePath = FileSettings.dataCollectionDir
                                                   + FileSettings.FILE_CLONE_START_END_BANK;
            String[][] clone_start_end_info =
                ArrayUtil.ReadRaggedStr2DArray(new File(clone_start_end_bank_filePath), false, " ");

            for (int cloneIndex = 0; cloneIndex < clone_start_end_info.length; cloneIndex++) {

                clone_index_Map.put(clone_start_end_info[cloneIndex][0], new Integer(cloneIndex));
            }


            // add the sequence info to the genes
            Iterator<Probe> itrGene = masterProbeSet.iterator();

            while (itrGene.hasNext()) {

                Probe probe      = itrGene.next();
                Integer indexObj = clone_index_Map.get(probe.getLabel());

                if (indexObj != null) {

                    int index = indexObj.intValue();

                    probe.setStartPos(Integer.parseInt(clone_start_end_info[index][1]));
                    probe.setEndPos(Integer.parseInt(clone_start_end_info[index][2]));
                }
            }

            IOUtil.marshall(new File(getObjectFilePath(Probe.class)), probeSetMap);

        } catch (IOException | NumberFormatException e) {
            e.printStackTrace();
        }
    }

    public void createCloneSetMap() {

        objFiles.put(Clone.class.getName(), dataCollectionDir + "CloneSet.obj");

        Map<Integer, Set<Clone>> cloneSetMap = new Hashtable<>();

        try {

            Map<String, Integer> clone_index_Map = new Hashtable<>();
            Set<Clone> masterCloneSet            = new HashSet<>();

            for (int ch_id_index = 0; ch_id_index < 7; ch_id_index++) {


                // get clone names
                String clone_names_filePath = FileSettings.dataCollectionDir
                                              + FileSettings.FILE_CLONE_NAME_PTRN
                                              + (ch_id_index + 1) + ".txt";
                String[] clone_names = IOUtil.getTokens(
                                           IOUtil.readFileContentToString(
                                               new File(clone_names_filePath)), null);
                Set<Clone> cloneSet = new HashSet<>();

                for (int cloneIndex = 0; cloneIndex < clone_names.length; cloneIndex++) {

                    Clone clone = new Clone();

                    clone.setLabel(clone_names[cloneIndex]);
                    clone.setOrder(cloneIndex + 1);
                    clone.setChId(ch_id_index + 1);
                    cloneSet.add(clone);
                }

                masterCloneSet.addAll(cloneSet);
                cloneSetMap.put(new Integer(ch_id_index + 1), cloneSet);
            }


            // add linkage groups for each clone by their labels
            Iterator<Clone> itr1 = masterCloneSet.iterator();

            while (itr1.hasNext()) {

                Clone clone1         = itr1.next();
                Iterator<Clone> itr2 = masterCloneSet.iterator();

                while (itr2.hasNext()) {

                    Clone clone2 = itr2.next();

                    if (clone1.getLabel().equals(clone2.getLabel())) {
                        clone1.addLinkageGroup(clone2.getChId());
                    }
                }

                int linkGrpCount = clone1.getLinkageGroupSet().size();
            }


            // read the clone_start_end bank and create a map for clone(key) with index(value)
            String clone_start_end_bank_filePath = FileSettings.dataCollectionDir
                                                   + FileSettings.FILE_CLONE_START_END_BANK;
            String[][] clone_start_end_info =
                ArrayUtil.ReadRaggedStr2DArray(new File(clone_start_end_bank_filePath), false, " ");

            for (int cloneIndex = 0; cloneIndex < clone_start_end_info.length; cloneIndex++) {

                clone_index_Map.put(clone_start_end_info[cloneIndex][0], new Integer(cloneIndex));
            }


            // add the sequence info to the clones
            Iterator<Clone> itrClone = masterCloneSet.iterator();

            while (itrClone.hasNext()) {

                Clone clone      = itrClone.next();
                Integer indexObj = clone_index_Map.get(clone.getLabel());

                if (indexObj != null) {

                    int index = indexObj.intValue();

                    clone.setStartPos(Integer.parseInt(clone_start_end_info[index][1]));
                    clone.setEndPos(Integer.parseInt(clone_start_end_info[index][2]));
                }
            }

            IOUtil.marshall(new File(getObjectFilePath(Clone.class)), cloneSetMap);

        } catch (IOException | NumberFormatException e) {
            e.printStackTrace();
        }
    }
}
